﻿using System;
using System.ComponentModel;
using System.Windows.Forms;

using Storm.TextEditor.Localization;

namespace Storm.TextEditor.Editor.Forms
{
	/// <summary>
	/// Represents the Find & Replace dialog of a TextEditor.
	/// </summary>
	public partial class FindReplace
		: Form
	{
		#region Fields

		private WeakReference weakControl    = null;
		private string        lastSearchText = "";

		#endregion

		#region Properties

		private new TextEditorBase Owner
		{
			get
			{
				if (weakControl != null)
					return (TextEditorBase)weakControl.Target;
				else
					return null;
			}
			set { weakControl = new WeakReference(value); }
		}

		#endregion

		#region Methods

		#region Public

		/// <summary>
		/// Shows the FindReplace to the user and sets it in "Find"-mode.
		/// </summary>
		public void ShowFind()
		{
			pnlReplace.Visible        = false;
			pnlReplaceButtons.Visible = false;

			this.Text = Localizations.FindDialogText;

			this.Show();
			this.Height = 160;

			btnDoReplace.Visible = false;
			btnReplace.Visible   = true;

			lastSearchText = "";
			cboFind.Focus();
		}

		/// <summary>
		/// Shows the FindReplace to the user and sets it in "Replace"-mode.
		/// </summary>
		public void ShowReplace()
		{
			pnlReplace.Visible        = true;
			pnlReplaceButtons.Visible = true;

			this.Text = Localizations.ReplaceDialogText;

			this.Show();
			this.Height = 200;

			btnDoReplace.Visible = true;
			btnReplace.Visible   = false;

			lastSearchText = "";
			cboFind.Focus();
		}

		/// <summary>
		/// Finds the next match from the text typed in the "Find"-textbox.
		/// </summary>
		public void FindNext()
		{
			string findText = cboFind.Text;

			if (lastSearchText != "" && lastSearchText != findText)
			{
				this.Owner.Caret.Position.X = 0;
				this.Owner.Caret.Position.Y = 0;
				this.Owner.ScrollIntoView();
			}

			lastSearchText = findText;

			if (findText == "")
				return;

			bool foundEarlierMatch = false;
			foreach (string earlierFindText in cboFind.Items)
			{
				if (earlierFindText == findText)
				{
					foundEarlierMatch = true;
					break;
				}
			}

			if (foundEarlierMatch == false)
				cboFind.Items.Add(findText);

			this.Owner.SelectNext(cboFind.Text, chkMatchCase.Checked, chkWholeWord.Checked, chkRegEx.Checked);
		}

		/// <summary>
		/// Finds all matches from the text typed in the "Find"-textbox and replaces the found matches with the text typed in the "Replace"-textbox.
		/// </summary>
		public void ReplaceAll()
		{
			string fintText = cboFind.Text;

			if (fintText == "")
				return;

			bool foundEarlierMatch = false;
			foreach (string earlierFindText in cboFind.Items)
			{
				if (earlierFindText == fintText)
				{
					foundEarlierMatch = true;
					break;
				}
			}

			if (foundEarlierMatch == false)
				cboFind.Items.Add(fintText);

			this.Owner.Caret.Position.X = 0;
			this.Owner.Caret.Position.Y = 0;

			while (this.Owner.SelectNext(cboFind.Text, chkMatchCase.Checked, chkWholeWord.Checked, chkRegEx.Checked))
				this.Owner.ReplaceSelection(cboReplace.Text);

			this.Owner.Selection.ClearSelection();
			cboFind.Focus();
		}

		/// <summary>
		/// Finds all matches from the text typed in the "Find"-textbox and bookmarks the rows they're in.
		/// </summary>
		public void MarkAll()
		{
			string findText = cboFind.Text;

			if (findText == "")
				return;

			bool foundEarlierMatch = false;
			foreach (string earlierFindText in cboFind.Items)
			{
				if (earlierFindText == findText)
				{
					foundEarlierMatch = true;
					break;
				}
			}

			if (foundEarlierMatch == false)
				cboFind.Items.Add(findText);

			this.Owner.Caret.Position.X = 0;
			this.Owner.Caret.Position.Y = 0;

			while (this.Owner.SelectNext(cboFind.Text, chkMatchCase.Checked, chkWholeWord.Checked, chkRegEx.Checked))
				this.Owner.Caret.CurrentRow.Bookmarked = true;

			this.Owner.Selection.ClearSelection();
			cboFind.Focus();
		}

		#endregion

		#region EventHandlers

		private void btnReplace_Click(object sender, EventArgs e)
		{
			this.ShowReplace();
		}

		private void btnReplaceAll_Click(object sender, EventArgs e)
		{
			this.ReplaceAll();
		}

		private void btnMarkAll_Click(object sender, EventArgs e)
		{
			this.MarkAll();
		}

		private void btnFind_Click(object sender, EventArgs e)
		{
			this.FindNext();
			cboFind.Focus();
		}

		private void btnDoReplace_Click(object sender, EventArgs e)
		{
			this.Owner.ReplaceSelection(cboReplace.Text);
			btnFind_Click(null, null);
		}

		private void btnClose_Click(object sender, EventArgs e)
		{
			this.Owner.Focus();
			this.Hide();
		}

		private void FindReplace_Closing(object sender, CancelEventArgs e)
		{
			e.Cancel = true;
			this.Hide();
		}

		#endregion

		#endregion

		/// <summary>
		/// Initializes a new instance of FindReplace.
		/// </summary>
		public FindReplace()
		{
			// Required by the Windows Forms Designer.
			InitializeComponent();

			btnFind.Text       = Localizations.FindNextButtonText;
			btnReplace.Text    = Localizations.FindReplaceButtonText;
			btnMarkAll.Text    = Localizations.FindMarkAllButtonText;
			btnReplaceAll.Text = Localizations.FindReplaceAllButtonText;
			btnClose.Text      = Localizations.FindCloseButtonText;

			lblFindWhat.Text    = Localizations.FindWhatLabelText;
			lblReplaceWith.Text = Localizations.FindReplaceWithLabelText;

			chkMatchCase.Text = Localizations.FindMatchCaseLabel;
			chkWholeWord.Text = Localizations.FindMatchWholeWordLabel;
			chkRegEx.Text     = Localizations.FindUseRegExLabel;
		}

		/// <summary>
		/// Initializes a new instance of FindReplace.
		/// </summary>
		/// <param name="owner">TextEditorBase control that will be the FindReplace's parent.</param>
		public FindReplace(TextEditorBase owner)
		{
			// Required by the Windows Forms Designer.
			InitializeComponent();

			this.Owner = owner;
		}
	}
}
